﻿using System.Security.Cryptography;
using System.Text;

namespace PmSoft.Core.Cryptos;

/// <summary>
/// 提供基于哈希算法的单向加密功能。
/// </summary>
public class HashUtility : IDisposable
{
	private readonly HashAlgorithm _hashAlgorithm;
	private bool _disposed;

	/// <summary>
	/// 初始化 <see cref="HashUtility"/> 类的新实例。
	/// </summary>
	/// <param name="hashAlgorithm">用于计算哈希的算法实例</param>
	/// <exception cref="ArgumentNullException">当 hashAlgorithm 为 null 时抛出</exception>
	public HashUtility(HashAlgorithm hashAlgorithm)
	{
		ArgumentNullException.ThrowIfNull(hashAlgorithm);
		_hashAlgorithm = hashAlgorithm;
		_disposed = false;
	}

	/// <summary>
	/// 计算输入字符串的哈希值。
	/// </summary>
	/// <param name="input">要计算哈希的字符串</param>
	/// <returns>哈希值字节数组</returns>
	/// <exception cref="ArgumentNullException">当输入字符串为 null 时抛出</exception>
	/// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
	public byte[] ComputeHash(string input)
	{
		if (_disposed)
			throw new ObjectDisposedException(nameof(HashUtility));

		ArgumentNullException.ThrowIfNull(input);

		byte[] inputBytes = Encoding.UTF8.GetBytes(input);
		return _hashAlgorithm.ComputeHash(inputBytes);
	}

	/// <summary>
	/// 计算输入字符串的哈希值并返回十六进制字符串。
	/// </summary>
	/// <param name="input">要计算哈希的字符串</param>
	/// <returns>十六进制格式的哈希值字符串</returns>
	public string ComputeHashHex(string input)
	{
		byte[] hashBytes = ComputeHash(input);
		return Convert.ToHexString(hashBytes).ToLowerInvariant();
	}

	/// <summary>
	/// 释放哈希算法使用的资源。
	/// </summary>
	public void Dispose()
	{
		if (!_disposed)
		{
			_hashAlgorithm.Dispose();
			_disposed = true;
		}
	}
}

/// <summary>
/// 提供创建常用哈希算法实例的工厂类。
/// </summary>
public static class HashUtilityFactory
{
	/// <summary>
	/// 创建 MD5 哈希算法实例。
	/// </summary>
	public static HashUtility CreateMd5() => new HashUtility(MD5.Create());

	/// <summary>
	/// 创建 SHA1 哈希算法实例。
	/// </summary>
	public static HashUtility CreateSha1() => new HashUtility(SHA1.Create());

	/// <summary>
	/// 创建 SHA256 哈希算法实例。
	/// </summary>
	public static HashUtility CreateSha256() => new HashUtility(SHA256.Create());

	/// <summary>
	/// 创建 SHA384 哈希算法实例。
	/// </summary>
	public static HashUtility CreateSha384() => new HashUtility(SHA384.Create());

	/// <summary>
	/// 创建 SHA512 哈希算法实例。
	/// </summary>
	public static HashUtility CreateSha512() => new HashUtility(SHA512.Create());
}